/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package pv1682010.gui;

import java.util.ArrayList;
import java.util.List;
import java.util.NavigableSet;
import java.util.ResourceBundle;
import java.util.concurrent.ExecutionException;
import javax.swing.SwingWorker;
import javax.swing.table.AbstractTableModel;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import pv1682010.Course;
import pv1682010.CourseManager;
import pv1682010.User;
import pv1682010.UserManager;

/**
 *
 * @author Isamaru
 */
public class EnrollmentTableModel extends AbstractTableModel {

    final private Logger log = LoggerFactory.getLogger(UserTableModel.class);
    final private CourseManager cm;
    final private UserManager um;
    final private Course course;
    private ResourceBundle translations;

    public EnrollmentTableModel(UserManager um, CourseManager cm, Course course) {
	super();
	if (um == null) {
	    throw new IllegalArgumentException("um");
	}
	if (cm == null) {
	    throw new IllegalArgumentException("cm");
	}
	if (course == null) {
	    throw new IllegalArgumentException("course");
	}
	this.um = um;
	this.cm = cm;
	this.course = course;
	translations = Translations.getRb();
	getUpdateSW().execute();
    }

    private List<AttendingUser> users = new ArrayList<AttendingUser>();

    @Override
    public int getRowCount() {
        return users.size();
    }

    @Override
    public int getColumnCount() {
        return 3;
    }

    @Override
    public String getColumnName(int columnIndex) {
	switch (columnIndex) {
	    case 0:
		return translations.getString("user_uco");
	    case 1:
		return translations.getString("user_name");
	    case 2:
		return translations.getString("enrollment");
	    default:
		throw new IllegalArgumentException("columnIndex");
	}
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        switch (columnIndex) {
            case 0:
                return users.get(rowIndex).getUser().getUco();
            case 1:
                return users.get(rowIndex).getUser().getName();
            case 2:
                return users.get(rowIndex).isAttending();
            default:
                throw new IllegalArgumentException("columnIndex");
        }
    }

@Override
public Class<?> getColumnClass(int columnIndex) {
    switch (columnIndex) {
        case 0:
            return Integer.class;
        case 1:
	    return String.class;
        case 2:
            return Boolean.class;
        default:
            throw new IllegalArgumentException("columnIndex");
    }
}

    @Override
    public boolean isCellEditable(int rowIndex, int columnIndex) {
	return (columnIndex == 2);
    }

    public void setUsers(List<AttendingUser> users) {
	this.users = users;
	fireTableDataChanged();
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
	if (columnIndex != 2) {
	    throw new IllegalArgumentException("columnIndex");
	}
	new EnrollSwingWorker(rowIndex, (Boolean) aValue).execute();
    }



    private SwingWorker<List<AttendingUser>, Void> getUpdateSW() {
	return new SwingWorker<List<AttendingUser>, Void>(){

	    @Override
	    protected void done() {
		try {
		    setUsers(get());
		} catch (InterruptedException ex) {
		    log.error("Exception thrown! ", ex);
		} catch (ExecutionException ex) {
		    log.error("Exception thrown! ", ex);
		}
	    }

	    @Override
	    protected List<AttendingUser> doInBackground() throws Exception {
		NavigableSet<User> enrolled = cm.getEnrolled(course);
		List<AttendingUser> users = new ArrayList<AttendingUser>();
		for (User user : um.getUsers()) {
		    users.add(new AttendingUser(user, enrolled.contains(user)));
		}
		return users;
	    }

	};
    }

    private class EnrollSwingWorker extends SwingWorker<Void, Void> {
	private AttendingUser user;
	private Integer rowIndex;
	private Boolean enrolled;

	public EnrollSwingWorker(Integer rowIndex, Boolean enrolled) {	    
	    this.rowIndex = rowIndex;
	    this.enrolled = enrolled;
	    user = users.get(rowIndex);
	}

	@Override
	protected void done() {
	    user.setAttending(enrolled);
	    fireTableCellUpdated(rowIndex, 2);
	}

	@Override
	protected Void doInBackground() throws Exception {
	    if (enrolled) {
		cm.enroll(course, user.getUser());
	    } else {
		cm.cancelEnrollment(course, user.getUser());
	    }
	    return null;
	}
    }
}
